<?php

namespace Xrfg\Api\Trading\Home\Controllers;

use App\Http\Controllers\Controller;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Xrfg\Api\Trading\Home\Models\Banner;
use Xrfg\Api\Trading\Home\Models\Prediction;
use Xrfg\Api\Trading\Home\Repositories\CoinPriceRepository;
use Xrfg\Api\Trading\Home\Resources\BannerResource;
use Xrfg\Api\Trading\Home\Resources\WebBannerResource;
use Xrfg\Api\Trading\Spot\Resources\RecommendSymbolResource;
use Xrfg\Core\Trading\Spot\Models\Pair;
use Xrfg\Api\Trading\Spot\Resources\SymbolResource;

class HomeController extends Controller
{
    /**
     * 首页轮播图.
     */
    public function banner()
    {
        return Cache::remember('home_banner', now()->addMinutes(10), function () { // 轮播图缓存10分钟
            $banners = Banner::select('title', 'picture', 'link')
                ->where('is_open', 1)
                ->where('type', 1)
                ->orderByDesc('sort')
                ->get();

            return BannerResource::collection($banners);
        });
    }

    /**
     * 首页轮播图-Web端.
     */
    public function webBanner()
    {
        return Cache::remember('home_web_banner', now()->addMinutes(10), function () { // 轮播图缓存10分钟
            $banners = Banner::select('title', 'picture', 'large_picture', 'link')
                ->where('is_open', 1)
                ->where('type', 2)
                ->orderByDesc('sort')
                ->get();

            return WebBannerResource::collection($banners);
        });
    }

    /**
     * 系统公告.
     */
    public function notice()
    {
        return Cache::remember('trading_notice', now()->addMinutes(10), function () { // 公告缓存10分钟
            $http = new Client();
            try {
                $response = $http->get('http://support.etf.cptcity.com/api/articleList?site_id=1&sortBy=created_at&sort=desc&category_id=1', [
                    'verify' => false,
                ]);
            } catch (\Exception $exception) {
                \Log::error($exception);

                return $this->array([]);
            }

            $content = $response->getBody()->getContents();
            $result = json_decode($content, true);

            $list = [];
            foreach ($result['data'] as $article) {
                $list[] = [
                    'id' => $article['id'],
                    'title' => $article['title'],
                    'html_url' => 'http://support.etf.cptcity.com/hc/articles/'.$article['id'],
                    'created_at' => date('Y-m-d H:i:s', strtotime($article['created_at'])),
                ];
            }

            return $this->array($list);
        });
    }

    /**
     * 首页推荐位交易对.
     */
    public function recommendSymbol()
    {
        $is_all = request('is_all');
        return Cache::remember('home_recommend_symbol', now()->addSecond(), function () use ($is_all) { // 缓存1秒钟
            $pairs = Pair::whereIn('status', [1, 2])
                ->where('is_recommend', 1)
                ->when($is_all != 1, function ($query) {
                    $query->limit(3);
                })
                ->get();

            return RecommendSymbolResource::collection($pairs);
        });
    }

    /**
     * 涨幅榜（前10名）.
     */
    public function changeRank()
    {
        return Cache::remember('home_change_rank', now()->addSecond(), function () { // 缓存1秒钟
            $http = new Client();
            try {
                $response = $http->get(route('api.spot.tickers'), [
                    'verify' => false,
                ]);
            } catch (\Exception $exception) {
                \Log::error($exception);

                return $this->array();
            }

            $content = $response->getBody()->getContents();
            $result = json_decode($content, true);
            if (200 != $result['code']) {
                return $this->array();
            }
            $symbols = $result['data'];
            // 计算涨跌幅
            foreach ($symbols as $k => $v) {
                $symbols[$k]['coin_name'] = explode('/', $v['symbol'])[0];
                $symbols[$k]['market_name'] = explode('/', $v['symbol'])[1];
                $symbols[$k]['change'] = (0 == $v['open']) ? 0 : (($v['close'] - $v['open']) / $v['open']);
            }
            // 涨跌幅逆序
            $symbols = collect($symbols)->sortByDesc('change')->toArray();
            // 移除相同币种名称
            $coinNameArr = [];
            foreach ($symbols as $key => $symbol) {
                if (in_array($symbol['coin_name'], $coinNameArr)) {
                    unset($symbols[$key]);
                } else {
                    array_push($coinNameArr, $symbol['coin_name']);
                }
            }
            // 取涨幅榜前10名
            return $this->array(array_values(collect($symbols)->take(10)->toArray()));
        });
    }

    /**
     * 成交额榜（前10名）.
     */
    public function tradesTotalRank()
    {
        return Cache::remember('home_trades_total_rank', now()->addSecond(), function () { // 缓存1秒钟
            $http = new Client();
            try {
                $response = $http->get(route('api.spot.tickers'), [
                    'verify' => false,
                ]);
            } catch (\Exception $exception) {
                \Log::error($exception);

                return $this->array();
            }

            $content = $response->getBody()->getContents();
            $result = json_decode($content, true);
            if (200 != $result['code']) {
                return $this->array();
            }
            $symbols = $result['data'];
            // 计算成交额
            foreach ($symbols as $k => $v) {
                $symbols[$k]['coin_name'] = explode('/', $v['symbol'])[0];
                $marketName = explode('/', $v['symbol'])[1];
                $symbols[$k]['market_name'] = $marketName;
                if ('USDT' == strtoupper($marketName)) {
                    $symbols[$k]['close_usd'] = $v['close'];
                    $symbols[$k]['total_usd'] = $v['total'];
                } else {
                    bcscale(8);
                    // 最新价转化为USDT
                    $symbols[$k]['close_usd'] = bcmul($v['close'], (new CoinPriceRepository())->coinToUsdt($marketName));
                    // 成交额转化为USDT
                    $symbols[$k]['total_usd'] = bcmul($v['total'], (new CoinPriceRepository())->coinToUsdt($marketName));
                }
            }
            // 成交额逆序
            $symbols = collect($symbols)->sortByDesc('total_usd')->toArray();
            // 移除相同币种名称
            $coinNameArr = [];
            foreach ($symbols as $key => $symbol) {
                if (in_array($symbol['coin_name'], $coinNameArr)) {
                    unset($symbols[$key]);
                } else {
                    array_push($coinNameArr, $symbol['coin_name']);
                }
            }
            // 取成交额榜前10名
            return $this->array(array_values(collect($symbols)->take(10)->toArray()));
        });
    }

    /**
     * 新币榜（最新上的10个币种）.
     */
    public function newCoinRank()
    {
        return Cache::remember('home_new_coin_rank', now()->addSecond(), function () { // 缓存1秒钟
            $pairs = Pair::whereIn('status', [Pair::STATUS_PRE_TRADING, Pair::STATUS_TRADING, Pair::STATUS_BREAK])
                ->orderByDesc('id')
                ->take(10)
                ->get();
            // 移除相同币种名称
            $coinNameArr = [];
            foreach ($pairs as $key => $pair) {
                if (in_array($pair['coin_name'], $coinNameArr)) {
                    unset($pairs[$key]);
                } else {
                    array_push($coinNameArr, $pair['coin_name']);
                }
            }

            return SymbolResource::collection($pairs);
        });
    }

    /**
     * 今日市场情绪预测.
     */
    public function todayMarketPredict($type)
    {
        if (!in_array($type, [1, 2])) {
            $this->error(90001);
        }

        if (Prediction::where('user_id', Auth::id())->where('created_at', '>', Carbon::today()->toDateTimeString())->exists()) {
            $this->error(90002);
        }

        try {
            // 删除历史预测数据
            Prediction::where('user_id', Auth::id())->delete();
            // 新增预测数据
            Prediction::create([
                'user_id' => Auth::id(),
                'type' => $type,
            ]);
            $times = Cache::get(now()->toDateString().'_trading_today_prediction_'.$type);
            Cache::put(now()->toDateString().'_trading_today_prediction_'.$type, $times + 1, now()->addDay());
        } catch (\Exception $e) {
            $this->error(500);
        }

        return $this->array($this->calPredictValue());
    }

    /**
     * 今日市场情绪预测统计值.
     */
    public function todayMarketPredictValue()
    {
        return $this->array($this->calPredictValue());
    }

    /**
     * 计算看多和看空比例.
     *
     * @return array
     */
    private function calPredictValue()
    {
        // 取alternative.me数据
        $rise_percent = Cache::remember('alternative_me_percent', now()->addHour(), function () { // 缓存1小时
            $http = new Client();
            try {
                $response = $http->get('https://api.alternative.me/fng/', [
                    'verify' => false,
                ]);
            } catch (\Exception $exception) {
                \Log::error('==api.alternative.me请求接口错误==');
                \Log::error($exception);

                return 50;
            }

            try {
                $content = $response->getBody()->getContents();
                $result = json_decode($content, true);

                return intval($result['data'][0]['value']);
            } catch (\Exception $exception) {
                \Log::error('==api.alternative.me解析数据错误==');
                \Log::error($exception);

                return 50;
            }
        });
        $fall_percent = 100 - $rise_percent;

        // 登录用户的投票状态
        if (Auth::id()) {
            $status = Prediction::where('user_id', Auth::id())
                    ->where('created_at', '>', Carbon::today()->toDateTimeString())
                    ->value('type') ?? 0;
        } else {
            $status = 0;
        }

        return [
            'rise_percent' => strval($rise_percent).'%',
            'fall_percent' => strval($fall_percent).'%',
            'status' => $status,
        ];
    }
}
